/*  SPDX-License-Identifier: GPL-2.0-or-later */
/*!********************************************************************

  Audacity: A Digital Audio Editor

  WaveBitmapCache.h

  Dmitry Vedenko

**********************************************************************/
#pragma once

#include <memory>

#include "GraphicsDataCache.h"
#include "Observer.h"
#include "waveform/WavePaintParameters.h"

class wxBitmap;
class wxImage;
class WaveDataCache;
class Envelope;
class WaveClip;

//! An element, that contains a rasterized bitmap matching the WaveDataCacheElement
class WAVE_TRACK_PAINT_API WaveBitmapCacheElement : public GraphicsDataCacheElementBase
{
public:
    ~WaveBitmapCacheElement() override;

    virtual uint8_t* Allocate(size_t width, size_t height) = 0;

    virtual size_t Width() const = 0;
    virtual size_t Height() const = 0;

    size_t AvailableColumns { 0 };
};

//! Cache containing rasterized bitmaps representing the waveform
class WAVE_TRACK_PAINT_API WaveBitmapCache final : public GraphicsDataCache<WaveBitmapCacheElement>
{
public:
    WaveBitmapCache(const WaveClip& waveClip, std::shared_ptr<WaveDataCache> dataCache, ElementFactory elementFactory);
    ~WaveBitmapCache() override;

    WaveBitmapCache& SetPaintParameters(const WavePaintParameters& params);
    WaveBitmapCache& SetSelection(const ZoomInfo& zoomInfo, double t0, double t1, bool selected);

private:
    bool InitializeElement(
        const GraphicsDataCacheKey& key, WaveBitmapCacheElement& element) override;

    void CheckCache(const ZoomInfo&, double, double) override;

    struct LookupHelper;

    WavePaintParameters mPaintParameters;

    struct
    {
        int64_t FirstPixel { -1 };
        int64_t LastPixel { -1 };

        bool IsValid() const noexcept
        {
            return FirstPixel < LastPixel;
        }
    } mSelection;

    std::unique_ptr<LookupHelper> mLookupHelper;

    const Envelope* mEnvelope { nullptr };
    size_t mEnvelopeVersion { 0 };

    const WaveClip& mWaveClip;
    Observer::Subscription mStretchChangedSubscription;
};
